package ru.chaykin.rendering;

import ru.chaykin.load.parse.MIFParser;
import ru.chaykin.primitives.Circle;
import ru.chaykin.util.Vector;
import ru.chaykin.viewobject.ViewObject;
import ru.chaykin.viewobject.texture.Texture;
import ru.chaykin.viewobject.texture.TextureFactory;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;

public class CullingTextThread extends CullingThread implements ITexConsts {
	
	public static final short TEX_BUFF_SIZE = 16;
	public static volatile ViewObject[] textureBuff = new ViewObject[TEX_BUFF_SIZE];
	
	public void run() {
		Log.d(getClass().getName(), "Thread started");
		boolean isnNull = false;
		while (isActive) {	//Ищем и "переискиваем" (т.к. область отображения меняется пользователем)
			for (int i = 0; i < TEX_BUFF_SIZE; i++) {
				synchronized(textureBuff) {// Вынесено отдельно и добавлена isnNull для минимизации времени в мониторе
					if (textureBuff[i] != null) {	//В буфере уже что-то есть...
						isnNull = true;
						bCircle = textureBuff[i].getBoundCircle(); //Узнаем область, в которой находится объект...
					} else {
						isnNull = false;
					}
				}
				if (isnNull) { //В буфере уже что-то есть...
					if (!bCircle.in(ra))  //Объект больше не попадает в область видимости 
						fillTexBuff(i); //Читаем новый из файла
				}
				else 
					fillTexBuff(i); //Читаем новый объект из файла
			}
		}
		Log.d(getClass().getName(), "Thread stoped");
	}
	
	/**
	 * Заполняет буфер текстур из отображенного на память файла
	 * @param index	- индекс, по которому заполняется буфер
	 */
	private final void fillTexBuff(int index) {
		do { // Пытаемся найти в файле объект, который попадает в область видимости
			synchronized(MIFParser.textureDataBuff) {
				indTotalNum = MIFParser.textureDataBuff.size();	//Количество объектов (т. к. загрузка происходит асинхронно, то в процессе работы потока размер может увеличиваться)
			}
			if (indTotalNum == 0)
				return;
			if (indNum >= indTotalNum)	//Если достигли конца, то начнем все сначала
				indNum = 0;
			synchronized(MIFParser.textureDataBuff) {
				bCircle = MIFParser.textureDataBuff.get(indNum).getCircle();
			}
			
			foundVisibleObject = false;
			if (bCircle.in(ra)) {//Объект попал в поле зрения
				boolean hasDouble = false;
				boolean notNull = true;
				Circle circle;
				for (int i = 0; i < TEX_BUFF_SIZE; i++) {
					synchronized(textureBuff) {
						notNull = (textureBuff[i] != null);
					}
					if (i != index && notNull)	{ //Сам себе, конечно, дубль, но это не в счет
						synchronized(textureBuff) {
							circle = textureBuff[i].getBoundCircle();
						}
						//Если объемлющие окружности совпадают, значит, это тот же объект, не будем его еще раз добавлять
						if (bCircle.equals(circle)) { 
							hasDouble = true;
							break;
						}
					}
				}
				if (!hasDouble)
					prepareTex(index);
			}
			indNum++; // Переходим к следующему объекту
		} while (!foundVisibleObject && isActive);	//Ищем, пока не найдем. (Если не найдем, то не найдем, все равно в потоке же. Как только подходящие объекты объявятся, выйдем из цикла :)
	}

	private final void prepareTex(int index) {
		float[] rect = new float[RECT_BUFF_SIZE];	//На этом прямоугольнике будет текстура с текстом
		int color;
		float pnts[];
		float alpha;
		int midIndex;
		String text;
		synchronized(MIFParser.textureDataBuff) {
			pnts = MIFParser.textureDataBuff.get(indNum).getRect();
			color = MIFParser.textureDataBuff.get(indNum).getColor();
			alpha = MIFParser.textureDataBuff.get(indNum).getAngle();
			text = MIFParser.textureDataBuff.get(indNum).getString();
			midIndex = MIFParser.textureDataBuff.get(indNum).getMIDInfoId();
		}
		rect[X0] = pnts[X0];
		rect[Y0] = pnts[Y0];
		rect[X1] = pnts[X1];
		rect[Y1] = pnts[Y1];
		
		Bitmap bm = Bitmap.createBitmap(Texture.TEX_PIXEL_WIDTH, Texture.TEX_PIXEL_HEIGHT, Bitmap.Config.ARGB_8888);
		bm.eraseColor(TRANSPARENCY_BACKGROUND);
		Canvas canvas = new Canvas(bm);
		
		Paint textPaint = new Paint();
		textPaint.setTextSize(FONT_SIZE);
		textPaint.setAntiAlias(true);
		textPaint.setColor(TRANSPARENCY_TEXT | color);
		canvas.rotate(-alpha, Texture.TEX_PIXEL_WIDTH / 2, Texture.TEX_PIXEL_HEIGHT / 2);
		float textPixelSize = textPaint.measureText(text);
		canvas.drawText(text, Texture.TEX_PIXEL_WIDTH / 2 - textPixelSize / 2, Texture.TEX_PIXEL_HEIGHT / 2 + 12, textPaint);
		
		
		float realTextWidth = Math.abs(rect[X0] - rect[X1]);
		float lambda = Texture.TEX_PIXEL_WIDTH / textPixelSize;
		float texSize = lambda * realTextWidth;
		Vector v = new Vector((rect[X0] + rect[X1]) / 2 - rect[X0], (rect[Y0] + rect[Y1]) / 2 - rect[Y1]);
		v.rotate(-alpha);
		rect[X0] = v.getX() + rect[X0] - texSize / 2f ;
		rect[Y0] = v.getY() + rect[Y1] - texSize / 2f ;
		rect[X1] = rect[X0] + texSize;
		rect[Y1] = rect[Y0];
		
		rect[X2] = rect[X0];
		rect[Y2] = rect[Y1] + texSize;
		rect[X3] = rect[X1];
		rect[Y3] = rect[Y2];
		
		synchronized(textureBuff) {
			textureBuff[index] = TextureFactory.genTexture(bCircle, index, midIndex, bm, rect);
		}
		foundVisibleObject = true;
	}
}
